#include "messageshowarea.h"
#include <QVBoxLayout>
#include <QTimer>
#include "debug.h"
#include "userinfowidget.h"
#include "model/data.h"
#include "model/datacenter.h"
#include "mainwidget.h"
#include "toast.h"

using namespace model;

/* ----------------------- 消息展示区 ---------------------------- */
MessageShowArea::MessageShowArea(QWidget *parent): QScrollArea{parent}
{
    // 1. 初始化基础属性
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    this->setWidgetResizable(true);
    this->setFrameShape(QFrame::NoFrame);

    // 2. 滚动条样式
    QScrollArea* temp = model::createScrollArea();
    this->setStyleSheet(temp->styleSheet());
    this->verticalScrollBar()->setStyleSheet(temp->verticalScrollBar()->styleSheet());
    this->horizontalScrollBar()->setStyleSheet(temp->horizontalScrollBar()->styleSheet());
    delete temp;

    // 3. 创建核心 widget
    container = new QWidget();
    container->setObjectName("showWidget");  // 防止级联问题
    container->setStyleSheet(R"(
        #showWidget{
            border-left: 1px solid rgb(213, 213, 213);
        })");
    this->setWidget(container);


    // 4. 给核心 Widget 添加布局
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setSpacing(5); // 每条消息之间的垂直间距
    layout->setContentsMargins(10, 10, 10, 10); // 整个消息显示区域的内边距
    layout->addStretch(); // 添加一个伸缩空间，让消息从顶部开始堆叠
        // 如果希望消息从底部开始堆叠，并且新消息添加到最底部，这个 addStretch 放在所有消息之后
        // 如果希望新消息添加到顶部（addFrontMessage），而旧消息往下推，那可能需要动态调整 stretch
    container->setLayout(layout);

#if TEST_UI
    for(int i = 0; i < 30; ++i){
        UserInfo userInfo;
        userInfo.nickname = "张三" + QString::number(i);
        userInfo.avatar = QIcon(":/resource/image/shuizhu.png");
        userInfo.userId = QString::number(i);
        userInfo.phone = "19628744563";
        userInfo.description = "努力！！！";
        // 制造一些长文本和短文本进行测试
        QString contentText;
        if (i % 2 == 0) {
            contentText = "这是一条简短的测试消息" + QString::number(i);
        } else {
            contentText = "这是一条非常非常长的测试消息，看看它是否能够正常地进行自动换行，并且气泡的宽度不会无限地拉伸，而是保持在一个合理的最大宽度内，高度会随着文本的增加而增加。" + QString::number(i) + " 再加点内容，让它更长一些，以便充分测试换行效果。";
        }
        Message message = Message::makeMessage(TEXT_TYPE, "",userInfo, contentText.toUtf8(), "");
        this->addMessage(i % 2 == 0, message); // 交替显示左右消息
    }
#endif

}

void MessageShowArea::addMessage(bool isLeft, const Message &message){
    MessageItem* messageItem = MessageItem::makeMessageItem(isLeft, message);
    container->layout()->addWidget(messageItem);
}

void MessageShowArea::addFrontMessage(bool isLeft, const Message &message){
    MessageItem* messageItem = MessageItem::makeMessageItem(isLeft, message);
    QVBoxLayout* layout = dynamic_cast<QVBoxLayout*>(container->layout());
    layout->insertWidget(0, messageItem);
}

void MessageShowArea::clear(){
    QLayout* layout = container->layout();
    for(int i = layout->count() - 1; i >= 0; i--){
        QLayoutItem* item = layout->takeAt(i);
        if(item->widget()){
            delete item->widget();
        }
        delete item;
    }
}

void MessageShowArea::scrollToEnd(){
    // 实现思路:
    // 拿到滚动区域中的滚动条(垂直滚动条), 获取到滚动条的最大值, 然后根据最大值设置滚动条位置.
    // 为使滚动效果更佳, 并能在界面绘制好之后进行滚动条的设置，给这里的滚动操作加个 "延时"
    QTimer* timer = new QTimer();
    connect(timer, &QTimer::timeout, this, [=]() {
        // 获取到垂直滚动条的最大值
        int maxValue = this->verticalScrollBar()->maximum();
        // 设置滚动条的滚动位置
        this->verticalScrollBar()->setValue(maxValue);

        timer->stop();
        timer->deleteLater();
    });
    timer->start(500);
}



/* ----------------------- 消息元素 ---------------------------- */
MessageItem::MessageItem(bool isLeft) : isLeft(isLeft)
{

}


MessageItem *MessageItem::makeMessageItem(bool isLeft, const Message &message){
    // 1. 创建对象和布局管理器
    MessageItem* messageItem = new MessageItem(isLeft);
    QGridLayout* layout = new QGridLayout();
    layout->setContentsMargins(10, 10, 10, 10);
    // layout->setSpacing(0);
    layout->setHorizontalSpacing(10);
    layout->setVerticalSpacing(10);

    messageItem->setMinimumHeight(180);
    messageItem->setLayout(layout);

    // 2. 创建头像
    QPushButton* avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(36, 36);
    avatarBtn->setIconSize(QSize(36, 36));
    // QPixmap srcAvatar = message.sender.avatar.pixmap(36, 36);
    // srcAvatar = model::getRoundRectPixmap(srcAvatar, QSize(36, 36), 8);
    // avatarBtn->setIcon(QIcon(srcAvatar));
    avatarBtn->setIcon(message.sender.avatar);

    // 3. 创建名字和时间
    QLabel* nameLabel = new QLabel();
    nameLabel->setText(message.sender.nickname + " | " + message.time);
    nameLabel->setAlignment(Qt::AlignBottom);
    nameLabel->setStyleSheet("QLabel { font: 400 11px 'Microsoft YaHei'; color: #666; }");

    // 4. 创建消息体
    QWidget* contentWidget = nullptr;
    switch (message.messageType) {
    case TEXT_TYPE:
        contentWidget = makeTextMessageItem(isLeft, message.content);
        break;
    case IMAGE_TYPE:
        contentWidget = makeImageMessageItem(isLeft, message.fileId, message.content);
        break;
    case FILE_TYPE:
        contentWidget = makeFileMessageItem(isLeft, message);
        break;
    case SPEECH_TYPE:
        contentWidget = makeSpeechMessageItem(isLeft, message);
        break;
    default:
        LOG() << "错误的消息类型! messageType=" << message.messageType;
    }

    // 5. 根据 isLeft 设置布局：利用 QGridLayout 的列和伸缩因子实现左右对齐
    if(isLeft){
        // 左侧消息：头像在最左边，内容区（名字+气泡）在中间，最右边是空白伸缩列
        layout->addWidget(avatarBtn, 0, 0, 2, 1, Qt::AlignTop | Qt::AlignLeft); // 头像：(0,0) 位置，占两行一列，左上对齐
        layout->addWidget(nameLabel, 0, 1, Qt::AlignBottom | Qt::AlignLeft);   // 名字：(0,1) 位置，左下对齐
        // layout->addWidget(contentWidget, 1, 1, Qt::AlignLeft);                 // 消息：(1,1) 位置，左对齐
        if(message.messageType == IMAGE_TYPE)
            layout->addWidget(contentWidget, 1, 1, 1, 2);
        else layout->addWidget(contentWidget, 1, 1);
        // 列伸缩因子：
        // 第0列 (头像): 固定大小，不伸缩
        // 第1列 (名字+内容): 允许伸缩，根据 MessageContentLabel 的 sizeHint 调整
        // 第2列 (空白): 弹性列，占据剩余大部分空间，将左侧内容推到左边
        layout->setColumnStretch(0, 0); // 头像列不伸缩
        layout->setColumnStretch(1, 1); // 名字和内容列，允许伸缩，权重为1
        layout->setColumnStretch(2, 5); // 空白列，更大的伸缩权重，将左侧内容推到左边
    }else{
        // 右侧消息：最左边是空白伸缩列，内容区（名字+气泡）在中间，头像在最右边
        layout->addWidget(avatarBtn, 0, 2, 2, 1, Qt::AlignTop | Qt::AlignRight); // 头像：(0,2) 位置，占两行一列，右上对齐
        layout->addWidget(nameLabel, 0, 1, Qt::AlignBottom | Qt::AlignRight);  // 名字：(0,1) 位置，右下对齐
        layout->addWidget(contentWidget, 1, 1, Qt::AlignRight);                // 消息：(1,1) 位置，右对齐
        // if(message.messageType == IMAGE_TYPE)
        //     layout->addWidget(contentWidget, 1, 1);
        // else layout->addWidget(contentWidget, 1, 1);

        // 列伸缩因子：
        // 第0列 (空白): 弹性列，占据剩余大部分空间，将右侧内容推到右边
        // 第1列 (名字+内容): 允许伸缩，根据 MessageContentLabel 的 sizeHint 调整
        // 第2列 (头像): 固定大小，不伸缩
        layout->setColumnStretch(0, 5); // 空白列，更大的伸缩权重，将右侧内容推到右边
        layout->setColumnStretch(1, 1); // 名字和内容列，允许伸缩，权重为1
        layout->setColumnStretch(2, 0); // 头像列不伸缩
    }

    // 设置 MessageItem 的最小高度为0，让它完全自适应内容
    messageItem->setMinimumHeight(0);
    // 设置 MessageItem 的 SizePolicy，宽度优先（Preferred），高度固定（Fixed），让布局来决定高度
    // 但在 QGridLayout 内部，通常设置为 Preferred, Preferred 也可以，让布局自行计算
    messageItem->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);


    // 6. 连接信号槽 -- 处理用户点击头像操作
    connect(avatarBtn, &QPushButton::clicked, messageItem, [=](){
        MainWidget* mainwidget = MainWidget::getInstance();
        UserInfoWidget* userInfoWidget = new UserInfoWidget(message.sender, mainwidget);
        userInfoWidget->exec();
    });

    // 7. 当用户修改了昵称的时候, 同步修改此处的用户昵称.
    if (!isLeft) {
        // 只是针对右侧消息(自己的消息) 做下列操作.
        DataCenter* dataCenter = DataCenter::getInstance();
        connect(dataCenter, &DataCenter::changeNicknameDone, messageItem, [=]() {
            nameLabel->setText(dataCenter->getMyself()->nickname + " | " + message.time);
        });

        connect(dataCenter, &DataCenter::changeAvatarDone, messageItem, [=]() {
            UserInfo* myself = dataCenter->getMyself();
            avatarBtn->setIcon(myself->avatar);
        });
    }

    return messageItem;
}

QWidget *MessageItem::makeTextMessageItem(bool isLeft, const QString &text){
    MessageContentLabel* item = new MessageContentLabel(text, isLeft, TEXT_TYPE, "", QByteArray());
    return item;
}

QWidget *MessageItem::makeImageMessageItem(bool isLeft, const QString& fileId, const QByteArray& content){
    MessageImageLabel* messageImageLabel = new MessageImageLabel(fileId, content, isLeft);
    return messageImageLabel;
}

QWidget *MessageItem::makeFileMessageItem(bool isLeft, const Message& message){
    MessageContentLabel* messageContentlable = new MessageContentLabel("[文件]" + message.fileName, isLeft, message.messageType,
                                                                        message.fileId, message.content);
    return messageContentlable;
}

QWidget *MessageItem::makeSpeechMessageItem(bool isLeft, const Message& message){
    return nullptr;
}

/* ----------------------- 文本消息正文部分 ---------------------------- */
MessageContentLabel::MessageContentLabel(const QString &text, bool isLeft, model::MessageType messageType,
                                         const QString &fileId, const QByteArray& content)
    : text(text), isLeft(isLeft), messageType(messageType), fileId(fileId), content(content)
{
    // 将 MessageContentLabel 的背景设置为透明，因为需要自己绘制背景
    setAttribute(Qt::WA_TranslucentBackground);
    // 不自动填充背景，避免默认的QWidget背景色干扰
    setAutoFillBackground(false);

    // 创建内部的 QLabel 来显示文本
    label = new QLabel(this); // 将 MessageContentLabel 作为 QLabel 的父对象
    label->setText(text);
    label->setWordWrap(true); // 开启自动换行
    label->setAlignment(Qt::AlignVCenter); // 垂直居中即可，水平对齐由 setGeometry 决定
    label->setStyleSheet(R"(
        QLabel {
            font: 400 14px 'Microsoft YaHei';
            color: #333;
            /* QLabel 自身的 padding 最好不要设置，由 paintEvent 中的 setGeometry 来控制 */
            /* padding: 0px; */
            line-height: 1.2;
            background-color: transparent;
        }
    )");
    label->setTextInteractionFlags(Qt::TextSelectableByMouse); // 允许复制

    // 针对文件消息, 并且 content 为空的情况下, 通过网络来加载数据
    if(messageType == model::TEXT_TYPE) return;
    if(this->content.isEmpty()){
        DataCenter* dataCenter = DataCenter::getInstance();
        connect(dataCenter, &DataCenter::getSingleFileDone, this, &MessageContentLabel::updateUI);
        dataCenter->getSingleFileAsync(this->fileId);
    }else{
        this->loadContentDone = true;
    }
}



// 核心：告诉布局管理器我的理想尺寸
QSize MessageContentLabel::sizeHint() const {
    QFontMetrics metrics(label->font()); // 使用内部 QLabel 的字体

    // 1. 确定气泡文本内容的 "最大可用宽度"
    // 这是气泡在换行前可以扩展到的最大宽度
    // 假设 MessageContentLabel 的父级是 MessageItem，MessageItem 的父级是 MessageShowArea 的 container
    int parentWidgetMaxWidth = 400; // 默认值，如果无法获取父级宽度
    if (parentWidget() && parentWidget()->parentWidget()) {
        // 获取 MessageShowArea 内部 container 的宽度 (整个聊天区域宽度)
        parentWidgetMaxWidth = parentWidget()->parentWidget()->width();
    }
    // 气泡文本内容的最大宽度 (占据总宽度的比例，并减去头像、间距等视觉上的占用)
    // 假设气泡最大宽度占聊天区域宽度的 MAX_BUBBLE_WIDTH_RATIO%
    // 还需要减去 MessageItem 左右为头像和间距预留的空间，假设是80px (40+40)
    int maxBubbleDisplayWidth = parentWidgetMaxWidth * MAX_BUBBLE_WIDTH_RATIO / 100;
    // 如果 MessageItem 自身也有限制，需要考虑
    if (maxBubbleDisplayWidth < 150) maxBubbleDisplayWidth = 150; // 最小宽度限制

    // 2. 计算文本在 "最大文本宽度" 下的实际尺寸
    // 这里传入的宽度是纯文本可以占用的区域，不包括气泡的内边距和箭头
    int contentTextAvailableWidth = maxBubbleDisplayWidth - TEXT_HORIZONTAL_PADDING - ARROW_WIDTH;
    if (contentTextAvailableWidth < 1) contentTextAvailableWidth = 1; // 避免0或负宽度

    // boundingRect() 会根据给定的最大宽度和 QFont::TextWordWrap 计算实际的文本矩形
    QRect textRect = metrics.boundingRect(QRect(0, 0, contentTextAvailableWidth, 0), Qt::TextWordWrap, text);
    int textActualWidth = textRect.width();
    int textActualHeight = textRect.height();

    // 3. 确定气泡的最终宽度
    int finalBubbleWidth;
    if (textActualWidth <= contentTextAvailableWidth) {
        // 文本没有达到换行点，气泡宽度包裹文本 (文本实际宽度 + 左右内边距 + 箭头宽度)
        finalBubbleWidth = textActualWidth + TEXT_HORIZONTAL_PADDING + ARROW_WIDTH;
    } else {
        // 文本已换行，气泡宽度固定为最大显示宽度
        finalBubbleWidth = maxBubbleDisplayWidth;
    }

    // 4. 确定气泡的最终高度
    // 气泡高度 = 文本实际高度 + 上下内边距
    int finalBubbleHeight = textActualHeight + TEXT_VERTICAL_PADDING;
    if (finalBubbleHeight < MIN_BUBBLE_HEIGHT) finalBubbleHeight = MIN_BUBBLE_HEIGHT; // 确保最小高度

    // qDebug() << "sizeHint: " << text << " -> " << QSize(finalBubbleWidth, finalBubbleHeight);
    return QSize(finalBubbleWidth, finalBubbleHeight);
}

QSize MessageContentLabel::minimumSizeHint() const {
    return sizeHint(); // 最小尺寸提示通常与尺寸提示相同
}

// 核心：绘制气泡背景、箭头，并定位 QLabel
void MessageContentLabel::paintEvent(QPaintEvent *event) {
    QPainter painter(this);
    QPainterPath path;
    painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿

    // 获取当前控件的实际宽度和高度 (由布局系统根据 sizeHint 设置)
    // 这是我们在 paintEvent 中唯一应该依赖的关于自身尺寸的信息
    int currentWidgetWidth = this->width();
    int currentWidgetHeight = this->height();

    // 气泡的实际宽度 (不含箭头) 和高度
    int bubbleRectWidth = currentWidgetWidth - ARROW_WIDTH;
    int bubbleRectHeight = currentWidgetHeight;

    // 绘制圆角矩形和箭头
    if (isLeft) {
        // 左侧气泡颜色：白色
        painter.setPen(QPen(QColor(255, 255, 255)));
        painter.setBrush(QColor(255, 255, 255));

        // 圆角矩形位置：从箭头宽度处开始
        int rectX = ARROW_WIDTH;
        int rectY = 0;
        painter.drawRoundedRect(rectX, rectY, bubbleRectWidth, bubbleRectHeight, BUBBLE_RADIUS, BUBBLE_RADIUS);

        // 绘制左侧箭头
        path.moveTo(ARROW_WIDTH, ARROW_Y_OFFSET);
        path.lineTo(0, ARROW_Y_OFFSET + ARROW_HEIGHT / 2); // 箭头尖端，中心点
        path.lineTo(ARROW_WIDTH, ARROW_Y_OFFSET + ARROW_HEIGHT);
        path.closeSubpath();
        painter.fillPath(path, QColor(255, 255, 255)); // 填充箭头

        // 设置 QLabel 的几何形状，使其位于气泡内部
        // QLabel 的左上角坐标，宽度和高度
        label->setGeometry(rectX + (TEXT_HORIZONTAL_PADDING / 2),
                           rectY + (TEXT_VERTICAL_PADDING / 2),
                           bubbleRectWidth - TEXT_HORIZONTAL_PADDING,
                           bubbleRectHeight - TEXT_VERTICAL_PADDING);
    } else {
        // 右侧气泡颜色：绿色
        painter.setPen(QPen(QColor(137, 217, 97)));
        painter.setBrush(QColor(137, 217, 97));

        // 圆角矩形位置：靠右对齐，预留箭头宽度
        int rectX = currentWidgetWidth - bubbleRectWidth - ARROW_WIDTH;
        int rectY = 0;
        painter.drawRoundedRect(rectX, rectY, bubbleRectWidth, bubbleRectHeight, BUBBLE_RADIUS, BUBBLE_RADIUS);

        // 绘制右侧箭头
        path.moveTo(currentWidgetWidth - ARROW_WIDTH, ARROW_Y_OFFSET);
        path.lineTo(currentWidgetWidth, ARROW_Y_OFFSET + ARROW_HEIGHT / 2); // 箭头尖端，中心点
        path.lineTo(currentWidgetWidth - ARROW_WIDTH, ARROW_Y_OFFSET + ARROW_HEIGHT);
        path.closeSubpath();
        painter.fillPath(path, QColor(137, 217, 97)); // 填充箭头

        // 设置 QLabel 的几何形状，使其位于气泡内部
        label->setGeometry(rectX + (TEXT_HORIZONTAL_PADDING / 2),
                           rectY + (TEXT_VERTICAL_PADDING / 2),
                           bubbleRectWidth - TEXT_HORIZONTAL_PADDING,
                           bubbleRectHeight - TEXT_VERTICAL_PADDING);
    }
    // qDebug() << "paintEvent: " << text << " -> " << this->geometry() << " Label: " << label->geometry();
}

void MessageContentLabel::mousePressEvent(QMouseEvent *event){
    if(event->button() == Qt::LeftButton){
        if(this->messageType == FILE_TYPE){
            qDebug() << "点击文件消息";
            saveAsFile(this->content);
            if(!this->loadContentDone){
                Toast::showMessage("数据尚未加载成功，请稍后重试");
                return;
            }
        }else if(this->messageType == SPEECH_TYPE){

        }else{
            // 其他消息
            qDebug() << "点击其他消息";
        }
    }
}

void MessageContentLabel::saveAsFile(const QByteArray &content){
    QString filePath = QFileDialog::getSaveFileName(this, "另存为", QDir::homePath(), "*");
    if(filePath.isEmpty()){
        LOG() << "用户取消了文件另存为";
        return;
    }
    writeByteArrayToFile(filePath, content);
}

void MessageContentLabel::updateUI(const QString &fileId, const QByteArray& fileContent){
    if(fileId != this->fileId) return;
    this->content = fileContent;
    this->update();
}


/* ----------------------- 消息元素 ---------------------------- */
MessageImageLabel::MessageImageLabel(const QString &fileId, const QByteArray &content, bool isLeft)
    :fileId(fileId), content(content), isLeft(isLeft)
{
    // this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    imageBtn = new QPushButton(this);
    imageBtn->setStyleSheet("QPushButton{border: none;}");

    if(content.isEmpty()){
        // 此处这个控件, 是针对 "从服务器拿到图片消息" 这种情况.
        // 拿着 fileId, 去服务器获取图片内容
        DataCenter* dataCenter = DataCenter::getInstance();
        connect(dataCenter, &DataCenter::getSingleFileDone, this, &MessageImageLabel::updateUI);
        dataCenter->getSingleFileAsync(fileId);
    }
    else {
        // 同步消息：立即设置 Icon
        setIconContent();
        updateGeometry(); // 触发 sizeHint 和布局更新
    }
    // 强制触发一次绘制，确保 imageBtn 被渲染出来
    // this->update();
}

// 辅助函数：计算缩放后的图片尺寸
QSize MessageImageLabel::calculateScaledImageSize(const QByteArray& imageContent) const {
    QImage image;
    // 1. 加载图片
    if(imageContent.isEmpty()){
        // 如果内容为空，使用默认图片的尺寸
        QByteArray tmpContent = loadFileToByteArray(":/resource/image/image.png");
        image.loadFromData(tmpContent);
    }else{
        image.loadFromData(imageContent);
    }

    // 2. 确定最大显示宽度
    // 这里的 maxWidth 应该基于 MessageShowArea 的宽度减去头像和间距等。
    // 假设 maxWidth 是整个聊天区域的一半
    int maxWidth = 400; // 默认值
    if (parentWidget() && parentWidget()->parentWidget()) {
        // 尝试获取 MessageShowArea 内部 container 的宽度的一半
        maxWidth = parentWidget()->parentWidget()->width() / 2;
    }
    if (maxWidth < 100) maxWidth = 100; // 最小宽度限制

    int finalWidth = image.width();
    int finalHeight = image.height();

    // 3. 等比例缩放
    if (image.width() > maxWidth) {
        // 图片太宽，需要缩放
        finalHeight = ((double)image.height() / image.width()) * maxWidth;
        finalWidth = maxWidth;
    }
    // 否则，保持原尺寸

    return QSize(finalWidth, finalHeight);
}


// 核心：告诉布局管理器我的理想尺寸
QSize MessageImageLabel::sizeHint() const {
    QSize scaledSize = calculateScaledImageSize(content);

    // 额外预留 20px 边距 (左右各 10px)，这与 paintEvent 中 imageBtn 的定位一致
    return QSize(scaledSize.width() + 20, scaledSize.height());
}

QSize MessageImageLabel::minimumSizeHint() const {
    return sizeHint();
}

// 图片加载完成后，通知布局更新
void MessageImageLabel::updateUI(const QString &fileId, const QByteArray &content){
    if(this->fileId != fileId){
        return ;
    }
    this->content = content;
    // 设置 Icon（使用新的辅助函数）
    setIconContent();

    // 触发布局更新，因为 sizeHint 和 MessageItem 的高度已改变
    updateGeometry();
    LOG()<<"服务器发送图片消息";
}

void MessageImageLabel::setIconContent()
{
    // 如果 content 为空，什么也不做，让 updateUI 处理异步加载
    if (content.isEmpty()) {
        return;
    }

    QSize scaledSize = calculateScaledImageSize(content);
    int width = scaledSize.width();
    int height = scaledSize.height();

    QImage image;
    // 1. 加载图片
    // 注意：这里需要重新实现加载图片的逻辑，因为它依赖 content
    if(!image.loadFromData(content)) {
        // 如果加载失败，尝试加载默认图片
        QByteArray tmpContent = loadFileToByteArray(":/resource/image/image.png");
        image.loadFromData(tmpContent);
    }

    QPixmap pixmap = QPixmap::fromImage(image.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation));

    // 2. 关键：只在这里设置 IconSize 和 Icon
    imageBtn->setIconSize(QSize(width, height));
    imageBtn->setIcon(QIcon(pixmap));

    // 无需调用 updateGeometry() 或 update()/repaint()，交给调用者处理
}

void MessageImageLabel::resizeEvent(QResizeEvent *event)
{
    // 保持不变，这是设置几何形状的正确位置。
    QWidget::resizeEvent(event);

    QSize scaledSize = calculateScaledImageSize(content);
    int width = scaledSize.width();
    int height = scaledSize.height();

    if (isLeft) {
        imageBtn->setGeometry(10, 0, width, height);
    } else {
        int leftPos = this->width() - width - 10;
        imageBtn->setGeometry(leftPos, 0, width, height);
    }
}


void MessageImageLabel::paintEvent(QPaintEvent *event){
    (void)event;
    // LOG()<<"onPaint响应";

    // 关键改动：移除所有设置 imageBtn Icon/Size 的代码！
    // 这些操作应该只在数据 (content) 变化时执行。

    // LOG()<<"图片消息~~~~~~";

    // 此时 paintEvent 只是一个日志记录器（如果不需要自定义绘制背景的话）。
    // 它不再执行任何可能导致重绘的副作用操作，从而避免了循环
}



// void MessageImageLabel::paintEvent(QPaintEvent *event){
//     (void)event;
//     LOG()<<"onPaint响应";
//     // 1. 先获取该元素的父元素
//     QObject* object = this->parent();
//     if(!object->isWidgetType()){
//         LOG()<<"onPaint中途退出";
//         return;
//     }
//     QWidget* parent = dynamic_cast<QWidget*>(object);
//     int width = parent->width()/2;
//     // 2. 加载二进制数据为图片对象
//     QImage image;
//     if(content.isEmpty()){
//         // 说明此时图片的响应数据还没回来.
//         QByteArray tmpContent = loadFileToByteArray(":/resource/image/image.png"); // 固定默认图片
//         image.loadFromData(tmpContent);
//     }else{
//         image.loadFromData(content);
//     }

//     // 3. 针对图片进行缩放
//     int height = 0;
//     if (image.width() > width) {
//         // 发现图片更宽, 就需要把图片缩放一下, 使用 width 作为实际的宽度
//         // 等比例缩放.
//         height = ((double)image.height() / image.width()) * width;
//     } else {
//         // 图片本身不太宽, 不需要缩放.
//         width = image.width();
//         height = image.height();
//     }

//     // pixmap 只是一个中间变量. QImage 不能直接转成 QIcon, 需要 QPixmap 中转一下
//     QPixmap pixmap = QPixmap::fromImage(image);
//     // imageBtn->setFixedSize(width, height);
//     imageBtn->setIconSize(QSize(width, height));
//     imageBtn->setIcon(QIcon(pixmap));
//     LOG()<<"图片消息~~~~~~";

//     // 4. 由于图片高度是计算算出来的. 该元素的父对象的高度, 能够容纳下当前的元素.
//     //    此处 + 50 是为了能够容纳下 上方的 "名字" 部分. 同时留下一点 冗余 空间.
//     parent->setFixedHeight(height + 50);

//     // 5. 确定按钮所在的位置. --> 左侧消息/右侧消息
//     if (isLeft) {
//         imageBtn->setGeometry(10, 0, width, height);
//     } else {
//         int leftPos = this->width() - width - 10;
//         imageBtn->setGeometry(leftPos, 0, width, height);
//     }
// }



















